package com.asman.vr.dto

import androidx.lifecycle.MutableLiveData
import androidx.paging.ItemKeyedDataSource
import com.asman.vr.constant.ErrorCode
import com.asman.vr.network.MyRetrofitCallback
import com.asman.vr.network.NetworkState
import retrofit2.Call
import java.util.concurrent.Executor

abstract class BaseItemKeyedDataSource<T>(private val retryExecutor: Executor) :
    ItemKeyedDataSource<String, T>() {

    private var retry: (() -> Any)? = null

    val networkState = MutableLiveData<NetworkState>()

    val initialLoad = MutableLiveData<NetworkState>()

    fun retryAllFailed() {
        val prevRetry = retry
        retry = null
        prevRetry?.let {
            retryExecutor.execute {
                it.invoke()
            }
        }
    }

    override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<T>) {
    }

    private var pageNOCurrent = 1
    private var pageNOLoading = 1 //正在加载的pageNo

    abstract fun queryTop(
        params: LoadInitialParams<String>,
        pageNo: Int
    ): Call<BaseRes<ListResult<T>>>

    abstract fun queryAfter(params: LoadParams<String>, pageNo: Int): Call<BaseRes<ListResult<T>>>

    override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<T>) {
        pageNOLoading++
        networkState.postValue(NetworkState.LOADING)

        queryAfter(params, pageNOLoading).enqueue(object : MyRetrofitCallback<ListResult<T>>() {
            override fun onSuccess(
                call: Call<BaseRes<ListResult<T>>>, result: ListResult<T>, datetime: String
            ) {
                val items = result.list?.map { it } ?: emptyList()
                retry = null
                callback.onResult(items)
                if (items.isEmpty()) {
                    networkState.postValue(NetworkState.NO_MORE)
                    pageNOLoading = pageNOCurrent
                } else {
                    networkState.postValue(NetworkState.LOADED)
                    pageNOCurrent = pageNOLoading
                }
            }

            override fun onError(
                errorType: ErrorType, call: Call<BaseRes<ListResult<T>>>, code: String, msg: String
            ) {
                super.onError(errorType, call, code, msg)
                retry = { loadAfter(params, callback) }
                networkState.postValue(NetworkState.error(msg))
                pageNOLoading = pageNOCurrent
            }
        })
    }

    //    override fun getKey(item: T): String = (item as RecordListData).data?.name!!

    override fun loadInitial(params: LoadInitialParams<String>, callback: LoadInitialCallback<T>) {
        pageNOLoading = 1
        pageNOCurrent = 1
        networkState.postValue(NetworkState.LOADING)
        initialLoad.postValue(NetworkState.LOADING)

        val request = queryTop(params, pageNOLoading)
        try {
            val response = request.execute()
            if (response.body()?.code == ErrorCode._10000) {
                val items = response.body()?.result?.list?.map { it } ?: emptyList()
                retry = null
                callback.onResult(items)
                if (items.isEmpty()) {
                    networkState.postValue(NetworkState.NO_MORE)
                    initialLoad.postValue(NetworkState.NO_MORE)
                } else {
                    networkState.postValue(NetworkState.LOADED)
                    initialLoad.postValue(NetworkState.LOADED)
                }
            } else {
                //是否拦截code error的情况下的默认操作--比如为true时，不进行跳转登录页面
                if (ErrorCode.tokenLoseEfficacy(response.body()?.code)) { //token 失效了
                    // todo sp
                    // sp.spExit()
                    //跳转登陆
                    //待测试
                    // todo 跳转页面
                    /*RouterUtils.get(RouterUrl.LoginChoiceActivity)
                        .navigation()*/
                }
                retry = {
                    loadInitial(params, callback)
                }
                val error = NetworkState.error(response.body()?.error)
                networkState.postValue(error)
                initialLoad.postValue(error)
            }
        } catch (exception: Exception) {
            retry = {
                loadInitial(params, callback)
            }
            val error = NetworkState.error(exception.message)
            networkState.postValue(error)
            initialLoad.postValue(error)
        }
        // 不能发起异步调用接口，否则会有问题--比如：列表自动滚动到中间位置
        //        queryTop(params, pageNOLoading).enqueue(object : MyRetrofitCallback<ListResult<T>>() {
        //            override fun onSuccess(call: Call<BaseRes<ListResult<T>>>, result: ListResult<T>?, datetime: String) {
        //                val items = result?.list?.map { it } ?: emptyList()
        //                retry = null
        //                callback.onResult(items)
        //                if (items.isEmpty()) {
        //                    networkState.postValue(NetworkState.NO_MORE)
        //                    initialLoad.postValue(NetworkState.NO_MORE)
        //                } else {
        //                    networkState.postValue(NetworkState.LOADED)
        //                    initialLoad.postValue(NetworkState.LOADED)
        //                }
        //            }
        //
        //            override fun onError(errorType: ErrorType, call: Call<BaseRes<ListResult<T>>>, code: Int?, msg: String?) {
        //                super.onError(errorType, call, code, msg)
        //                retry = {
        //                    loadInitial(params, callback)
        //                }
        //                val error = NetworkState.error(msg)
        //                networkState.postValue(error)
        //                initialLoad.postValue(error)
        //            }
        //        })
    }
}